package com.ruoyi.chat.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.chat.constant.RagFlowCode;
import com.ruoyi.chat.domain.Chat;
import com.ruoyi.chat.domain.ChatDataset;
import com.ruoyi.chat.domain.Dataset;
import com.ruoyi.chat.exception.ragFlowReqException;
import com.ruoyi.chat.http.RagFlowUtils;
import com.ruoyi.chat.mapper.ChatMapper;
import com.ruoyi.chat.mapper.DatasetMapper;
import com.ruoyi.chat.service.IChatDatasetService;
import com.ruoyi.chat.service.IChaterService;
import com.ruoyi.chat.service.IDatasetService;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.chat.request.chat.ChatRequest;
import com.ruoyi.common.utils.ArraysUtils;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 聊天助手Service业务层处理
 * 
 * @author ruoyi
 * @date 2025-03-26
 */
@Service
public class ChaterServiceImpl implements IChaterService
{

    private static final Logger log = LoggerFactory.getLogger(ChaterServiceImpl.class);

    @Autowired
    private ChatMapper chatMapper;

    @Autowired
    private DatasetMapper datasetMapper;

    @Autowired
    private IDatasetService datasetService;

    @Autowired
    private IChatDatasetService chatDatasetService;

    /**
     * 查询聊天助手
     * 
     * @param id 聊天助手主键
     * @return 聊天助手
     */
    @Override
    public Chat selectChatById(Long id)
    {
        Chat chat = chatMapper.selectChatById(id, getLoginUser().getUserId());
        if (chat == null) {
            throw new ragFlowReqException("您无权限使用该聊天助手");
        }
        // 对当前助理进行鉴权
        checkChatAuth(new Long[]{id});
        return chat;
    }

    /**
     * 查询聊天助手列表
     * 
     * @param chat 聊天助手
     * @return 聊天助手
     */
    @Override
    public List<Chat> selectChatList(Chat chat)
    {
        // 查询知识库列表接口不用鉴权 - 展示个人所有助手，对知识库的鉴权放在详情接口中
        chat.setUserId(getLoginUser().getUserId());
        return chatMapper.selectChatList(chat);
    }

    /**
     * 新增聊天助手
     * 
     * @param chat 聊天助手
     * @return 结果
     */
    @Override
    public int insertChat(Chat chat)
    {
        chat.setCreateTime(DateUtils.getNowDate());
        return chatMapper.insertChat(chat);
    }

    @Override
    @Transactional
    public int add(Chat chat, String url) {
        // 鉴权 - 如果包含知识库 则需要知识库鉴权
        if (!ArraysUtils.isBlank(chat.getChatDataIds())) {
            datasetService.checkAuth(chat.getChatDataIds());
        }
        // 先本地存储
        chat.setUserId(getLoginUser().getUserId());
        int rows = this.insertChat(chat);
        // 关联 聊天助手 - 知识库
        chatDatasetService.chatDatasetRelate(chat.getId(), Arrays.asList(chat.getChatDataIds()));
        // 请求ragFlow
        ChatRequest request = new ChatRequest();
        BeanUtils.copyProperties(chat, request);
        request.setDatasetIds(getRagDataSetIds(chat.getChatDataIds()));
        JSONObject postResult = RagFlowUtils.sendPost(url, JSONObject.from(request));
        JSONObject successInfo = JSONObject.from(postResult.get(RagFlowCode.DATA));
        // 回填聊天助手id(ragFlow)
        chat.setRagChatId(String.valueOf(successInfo.get("id")));
        this.updateChat(chat);
        return rows;
    }

    /**
     * 修改聊天助手
     * 
     * @param chat 聊天助手
     * @return 结果
     */
    @Override
    public int updateChat(Chat chat)
    {
        chat.setUpdateTime(DateUtils.getNowDate());
        return chatMapper.updateChat(chat);
    }

    @Override
    @Transactional
    public int update(Chat chat, String url) {
        // 鉴权(包含知识库和助手的双重鉴权)
        checkChatAuth(new Long[]{chat.getId()});
        // 先本地更新
        int rows = this.updateChat(chat);
        // 关联 聊天助手 - 知识库
        chatDatasetService.chatDatasetRelate(chat.getId(), Arrays.asList(chat.getChatDataIds()));
        // 请求ragFlow
        ChatRequest request = new ChatRequest();
        BeanUtils.copyProperties(chat, request);
        request.setDatasetIds(getRagDataSetIds(chat.getChatDataIds()));
        RagFlowUtils.sendPut(url, JSONObject.from(request));
        return rows;
    }

    /**
     * 批量删除聊天助手
     * 
     * @param ids 需要删除的聊天助手主键
     * @return 结果
     */
    @Override
    public int deleteChatByIds(Long[] ids)
    {
        return chatMapper.deleteChatByIds(ids);
    }

    @Override
    @Transactional
    public int delete(Long[] ids, String url) {
        // 鉴权(包含知识库和助手的双重鉴权)
        List<Chat> chats = checkChatAuth(ids);

        // 先本地删除
        int rows = this.deleteChatByIds(ids);
        // todo 清除 知识库---聊天助手 关联关系

        ChatRequest request = new ChatRequest();
        List<String> ragChatIds =  chats.stream().map(Chat::getRagChatId).collect(Collectors.toList());
        request.setIds(ragChatIds);
        RagFlowUtils.sendDelete(url, JSONObject.from(request));
        return rows;
    }

    /**
     * 删除聊天助手信息
     * 
     * @param id 聊天助手主键
     * @return 结果
     */
    @Override
    public int deleteChatById(Long id)
    {
        return chatMapper.deleteChatById(id);
    }

    public List<Chat> checkChatAuth(Long[] inputIds) {
        // 有问题会抛出异常(已包含知识库的鉴权)
        if (ArraysUtils.isBlank(inputIds)) {
            log.error("请先选择智能助手");
            throw new ragFlowReqException("请先选择智能助手");
        }
        // 先入参去重
        Long[] ids = Arrays.stream(inputIds).distinct().toArray(Long[]::new);
        List<Chat> chats = chatMapper.selectChatsByIds(ids, getLoginUser().getUserId());
        if (CollectionUtils.isEmpty(chats) || chats.size() < ids.length) {
            log.error("您无权限操作当前助手");
            throw new ragFlowReqException("您无权限操作当前助手");
        }
        // 鉴权知识库 - 聊天助手平铺所有知识库 再汇聚所有的知识库id 去重后鉴权
        Long[] dataSetIds = chats.stream()
                .flatMap(chat -> chat.getChatDatasets().stream())
                .map(ChatDataset::getDatasetId)
                .distinct()
                .toArray(Long[]::new);
        // 如果不存在知识库 则无须对知识库进行鉴权
        if (ArraysUtils.isBlank(dataSetIds)) {
            return chats;
        }
        datasetService.checkAuth(dataSetIds);
        return chats;
    }

    // 通过本地知识库id - 查询ragFlow上的知识库id
    private List<String> getRagDataSetIds(Long[] dataSetIds) {
        if (ArraysUtils.isBlank(dataSetIds)) {
            return Collections.emptyList();
        }
        List<Dataset> datasets = datasetMapper.selectDatasetByIds(dataSetIds, getLoginUser().getUserId(), SecurityUtils.getRoleIds());
        if (CollectionUtils.isEmpty(datasets)) {
            throw new ragFlowReqException("添加智能助手出错：知识库不存在");
        }
        return datasets.stream().map(Dataset::getRagDatasetId).collect(Collectors.toList());
    }

    /**
     * 获取用户缓存信息
     */
    public LoginUser getLoginUser()
    {
        return SecurityUtils.getLoginUser();
    }
}
